const FUN = require('../comm/func');
const rCache = require('../model/redis_cache');
const timLib = require('../comm/time-lib');
const mbLib = require('../comm/modbus-lib');
const PMR = require('../utils/policyManger');
const devManger = require('../utils/devManger');
const tbLog = require('../model/tb_log');

const ONE_DAY_SEC = 86400;

module.exports = class Tim_Mq_D
{
  // 将数据库选项缓存到redis
  // policy 来自数据库的记录，附加了user_auth字段
  // opts 数据库json字段的解析对象
  // CacheCallback 存储执行函数
  static InitCache(policy, opts, CacheCallback)
  {
    if (FUN.isLocal()) return false; // 不允许本地运行，调试时注意屏蔽此句
    let obj = PMR.baseParam(policy);//即将缓存到redis的参数
    // obj.user_auth = policy.user_auth;//用户权限

    //检查json选项
    if( opts.time.length == 0 || opts.data.length == 0 ) {
      pcyErr('wrong Tim_Mq_d params', policy.id);
      return false;
    }

    //参数预处理
    let time = opts.time.split(';'); // 分解定时时间
    let msNum = [];
    if (time.length == 0) return false;
    for (let t of time) {
      let t1 = t.split(':');
      if(t1.length != 2) return false;
      let h = t1[0]*3600;
      let m = t1[1]*60;
      msNum.push((h+m)*1000); // 将时间换算成时间戳
    }

    msNum.sort((a,b)=>a-b); // 从小到大排序
    obj.time = msNum.join(';');
    opts.data = opts.data.replace(/[\n]/g, ''); // 去掉换行
    opts.data = opts.data.replace(/[;]$/g, ''); // 去掉末尾分号
    obj.data = opts.data; //数据

    // 找出当前排序
    let nowStamp = timLib.NowStamp();
    nowStamp = nowStamp - timLib.Rounding(ONE_DAY_SEC);
    let count = 0;
    for (let t of msNum) {
      if (t > nowStamp) break;
      count++;
    }

    let secGap = 0;
    if (count == msNum.length) { // 今天的所有时间都已经过了
      secGap = (ONE_DAY_SEC*1000 + msNum[0] - nowStamp) / 1000; // 定时到明天
      count = 0;
    } else {
      secGap = (msNum[count] - nowStamp) / 1000; // 定时到今天
    }
    //pcyLog('tim set',count,~~secGap,~~(secGap/3600),~~(secGap%3600/60));

    obj.type = opts.topic;
    obj.hwid = policy.master;
    obj.hwtype = FUN.Hwid2TypeName(policy.master);

    switch (opts.topic) {
      case 'var':
        obj.topic = `0/${obj.hwtype}/${opts.topic}/0-${obj.hwid}`;
        break;
      default:
        obj.topic = `0/${obj.hwtype}/${opts.topic}/${obj.hwid}`;
    }

    CacheCallback(policy.id, policy.master,obj); // 记录到缓存

    // 循环计数
    rCache.setKey(PMR.rdNode(obj), 'count', count, ONE_DAY_SEC);

    // 开启定时器
    PMR.setSecInter(obj.policy_id, ~~secGap);
    // pcyLog(`[${obj.policy_id}] Init set timer`, ~~secGap);
  }//end InitCache

  // 处理数据
  // topic = {project,devType,func,devId}
  // dConf即InitCache中的obj
  // dataBuf即mq消息内容，buf对象
  static async DataIn(topic, dConf, DataBuf)
  {
    return;
  }

  // 发数据包
  static PubDataTopic(topic, dataStr)
  {
      let dArray = dataStr.split(' ');
      let sendArray = [];

      for (let c of dArray) {
        if (c == '#c') {
          let crc = mbLib.crc16(sendArray);
          sendArray.push(crc>>8);
          sendArray.push(crc&0xff);
        } else {
          if (!isNaN(parseInt(c,16))) sendArray.push(parseInt(c,16));
        }
      }

      PMR.mqPub(topic, Buffer.from(sendArray));
  }

  // 发json包
  static PubVarTopic(topic, jsonStr)
  {
    try {
      let jsonObj = JSON.parse(jsonStr);
      PMR.mqPub(topic, JSON.stringify(jsonObj), {retain:true});
    } catch (error) {
      pcyErr(`[${topic}] tim-mq-d: json parse error!`);
    }
  }

  // 周期回调
  static SecInter(dConf, nowStamp)
  {
    let msNum = dConf.time.split(';');

    rCache.getKey(PMR.rdNode(dConf), 'count').then(count=>{
      let n = count % msNum.length; // 决定次序
      let logStr = 'NONE';

      if (dConf.data && dConf.data.length > 0) {
        let pktStr = dConf.data.split(';');
        if (pktStr[n] && pktStr[n].length > 0) {
          if (dConf.type == 'var') this.PubVarTopic(dConf.topic, pktStr[n]);
          else this.PubDataTopic(dConf.topic, pktStr[n]);
          logStr = pktStr[n];
        }
      }
      tbLog.newDevLog(dConf.uid, dConf.hwid, 8000, `[policy tim-d] [${n}] ${logStr}`, nowStamp);

      // 下一次定时
      n++;
      let secGap = 0;
      let nextStamp = nowStamp - timLib.Rounding(ONE_DAY_SEC);
      if (n >= msNum.length) {
        secGap = (ONE_DAY_SEC*1000+parseInt(msNum[0])-nextStamp) / 1000; // 定时到明天
      } else {
        secGap = (parseInt(msNum[n])-nextStamp) / 1000; // 定时到今天
      }
      PMR.setSecInter(dConf.policy_id, ~~secGap); // 定时
      // pcyLog(`[${dConf.policy_id}] Next set timer`, ~~secGap, ~~(secGap/3600), ~~(secGap%3600/60));

      // 调试记录
      rCache.incKey(PMR.rdNode(dConf), 'count', ONE_DAY_SEC); // 计数
    })
  }//end function



}